import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Code4 {
    /*
     * 线程安全问题
     * 线程操作同一个数据的时候 多个线程的执行时机是随机的
     * 可能会出现多个线程同时操作同一个数据的情况
     * 为了解决这个情况 我们需要加锁
     *
     * synchronized 锁参数的对象一定要是唯一的
     *
     * 锁的作用是：
     * 1. 确保在任意时刻只有一个线程可以执行被锁保护的代码块
     * 2. 防止多个线程同时修改共享数据导致的数据不一致问题
     *
     * synchronized 这种方式叫同步代码块
     * synchronized可以对标js的await
     * */
//    public static void main(String[] args) {
//
//        MyThread myThread1 = new MyThread();
//        MyThread myThread2 = new MyThread();
//        MyThread myThread3 = new MyThread();
//        myThread1.setName("窗口1");
//        myThread2.setName("窗口2");
//        myThread3.setName("窗口3");
//        myThread1.start();
//        myThread2.start();
//        myThread3.start();
//    }
//
//    public static class MyThread extends Thread {
//        static int ticker = 0;
//        @Override
//        public void run() {
//            while (true) {
//                synchronized (Code4.class) {
//                    try {
//                        Thread.sleep(10);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                    if (ticker < 100) {
//                        ticker++;
//                        System.out.println(this.getName() + "正在卖第" + ticker + "号票");
//                    } else {
//                        break;
//                    }
//                }
//            }
//        }
//    }


//    public static void main(String[] args) {
//
//        MyRunnable myRunnable = new MyRunnable();
//
//        Thread t1 = new Thread(myRunnable);
//        Thread t2 = new Thread(myRunnable);
//        Thread t3 = new Thread(myRunnable);
//        t1.setName("窗口1");
//        t2.setName("窗口2");
//        t3.setName("窗口3");
//        t1.start();
//        t2.start();
//        t3.start();
//    }
//
//    public static class MyRunnable implements Runnable {
//        int ticker = 0;
//        @Override
//        public void run() {
//            while (true) {
//                    if (extracted()) break;
//            }
//        }
//
//        /*
//        * synchronized 加在方法前面 表示这个方法是一个同步方法
//        * 当一个线程调用这个方法的时候 其他线程只能等待
//        * */
//        private synchronized boolean  extracted() {
//            if(ticker==100){
//                return true;
//            }else{
//                try {
//                    Thread.sleep(10);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//                ticker++;
//                System.out.println(Thread.currentThread().getName() + "正在卖第" + ticker + "号票");
//            }
//            return false;
//        }
//    }





    /*
     * 使用Look 可以开关锁
     *
     * */

//    public static void main(String[] args) {
//
//        MyThread myThread1 = new MyThread();
//        MyThread myThread2 = new MyThread();
//        MyThread myThread3 = new MyThread();
//        myThread1.setName("窗口1");
//        myThread2.setName("窗口2");
//        myThread3.setName("窗口3");
//        myThread1.start();
//        myThread2.start();
//        myThread3.start();
//    }
//
//    public static class MyThread extends Thread {
//        static int ticker = 0;
//
//        static Lock lock = new ReentrantLock();
//
//        @Override
//        public void run() {
//            while (true) {
//                lock.lock();
//                try {
//                    if (ticker == 100) {
//                        break;
//                    } else {
//                        ticker++;
//                        System.out.println(this.getName() + "正在卖第" + ticker + "号票");
//                    }
//                    Thread.sleep(10);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                } finally {
//                    lock.unlock();
//                }

    /// /                不能直接把解锁的代码写在最下方
    /// /                不让会直接在if语句中跳出循环 锁永远无法被释放
    /// /                解锁的代码要放在finally中
    /// /                lock.unlock();
//            }
//        }
//    }




    /*
     * 死锁
     * 死锁的形成原因就是
     * 1. 多个线程同时请求锁
     * 2. 每个线程都在等待其他线程释放锁
     *
     * 避免死锁的形成
     * 1. 不要嵌套请求锁
     * 2. 不要在一个线程中请求多个锁
     * */


}
